package ltd.dujiabao.mavenLocalInstaller.jar;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.PropertyResourceBundle;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import ltd.dujiabao.mavenLocalInstaller.domain.PomProperties;
import ltd.dujiabao.mavenLocalInstaller.domain.PomPropertiesBuilder;
import ltd.dujiabao.mavenLocalInstaller.util.PathUtils;

/**
 * @author : DuJiabao
 * @Project : mavenLocalInstaller
 * @Time : 2021/9/28 22:56
 * @Desc : jar包一般包含 BOOT-INF、META-INF等文件夹。
 * 其中，BOOT-INF中可能会包含lib文件夹，lib文件夹中包含运行该jar包的其他依赖jar包
 * META-INF包含该jar包的pom信息，可利用pom包定位该jar包在maven仓库中保存的路径
 */


public class JarReader {
    /**
     * 返回本Jar包的 pom 信息
     *
     * @param filePath Jar包绝对路径
     */
    public static PomProperties getPomProperties(String filePath) {
        try (JarFile jarFile = new JarFile(filePath)) {
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry element = entries.nextElement();
                String elementName = element.getName();
                if (elementName.endsWith("pom.properties") && elementName.startsWith("META-INF/maven")) {
                    InputStream pomFileStream = jarFile.getInputStream(element);
                    PropertyResourceBundle resource = new PropertyResourceBundle(pomFileStream);
                    String version = resource.getString("version");
                    String groupId = resource.getString("groupId");
                    String artifactId = resource.getString("artifactId");
                    return new PomPropertiesBuilder()
                            .setGroupId(groupId)
                            .setArtifactId(artifactId)
                            .setVersion(version)
                            .build();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读jar文件，并且利用biConsumer消费它
     *
     * @param filePath   jar文件绝对路径
     * @param biConsumer 消费方法
     */
    public static void readAndConsumerJarFile(String filePath, BiConsumer<JarFile, JarEntry> biConsumer) {
        try (JarFile jarFile = new JarFile(filePath)) {
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry element = entries.nextElement();
                biConsumer.accept(jarFile, element);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 提取jar包中的子jar包到指定的目录，默认覆盖存在的文件
     *
     * @param filePath jar文件的绝对路径
     * @param destDir  destDir 绝对路径的目录
     */
    public static List<String> saveSubJarFile(String filePath, String destDir) {
       return saveSubJarFile(filePath, destDir, StandardCopyOption.REPLACE_EXISTING);
    }

    /**
     * 提取jar包中的子jar包到指定的目录
     *
     * @param filePath   jar文件的绝对路径
     * @param destDir    destDir 绝对路径的目录
     * @param copyOption 复制选项，可通过 StandardCopyOption 选择
     */
    public static List<String> saveSubJarFile(String filePath, String destDir, CopyOption copyOption) {
        final String dir = PathUtils.ensureEndWithSeparator(destDir);
        List<String> destPathList = new ArrayList<>();
        AtomicLong count = new AtomicLong(0);
        readAndConsumerJarFile(filePath, (jarFile, jarEntry) -> {
            String elementName = jarEntry.getName();
            if (elementName.startsWith("BOOT-INF/lib") && elementName.endsWith(".jar")) {
                String fileName = elementName.substring(13);
                try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
                    String destPath = dir + fileName;
                    Files.copy(inputStream, Paths.get(destPath), copyOption);
                    count.getAndIncrement();
                    destPathList.add(destPath);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        System.out.println("Found " + count.get() + " jar files in " + filePath + ". Have saved in " + destDir);
        return destPathList;
    }

    public static void main(String[] args) {
        saveSubJarFile(PathUtils.getPath("standard_server-0.0.1-SNAPSHOT.jar"), "E:\\tools\\mavenLocalInstaller\\src\\main\\resources\\");
    }
}
